<template>
  <div>
    <!--    <div class="w-full h-[600px] bg-black border border-transparent">-->
    <!--      <div class="w-[100px] h-[100px] bg-red-700 red mt-8" />-->
    <!--      <div class="w-[100px] h-[100px] bg-green-700 green mt-8" />-->
    <!--      <div class="w-[100px] h-[100px] bg-purple-700 purple mt-8" />-->
    <!--      <div class="w-[100px] h-[100px] bg-orange-700 orange mt-8" />-->
    <!--    </div>-->
    <!--    视觉滚动 -->

    <div class="parallax-container h-screen">
      <div
        v-for="(item, index) in parallaxItems"
        :key="index"
        class="parallax-item w-full h-screen"
        :style="{ backgroundImage: `url(${item.image})` }"
      >
        <div class="text">
          <p>{{ item.text }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive } from "vue";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger.js";
// 注册 ScrollTrigger 插件
gsap.registerPlugin(ScrollTrigger);
const parallaxItems = reactive([
  {
    image: "https://picsum.photos/200/300?random=" + Math.random() * 10,
    text: "视觉滚动"
  },
  {
    image: "https://picsum.photos/200/300?random=" + Math.random() * 10,
    text: "视觉滚动"
  },
  {
    image: "https://picsum.photos/200/300?random=" + Math.random() * 10,
    text: "视觉滚动"
  }
]);

import { nextTick } from "vue";
defineOptions({
  name: "GsapDemo"
});
// 学习
nextTick(() => {
  // const box = document.querySelector(".gbox");
  // gsap.to：最常用的动画类型，从当前状态开始。 transform: translate(200px, 0px)
  // gsap.to(box, { x: 500 }); // CSS选择器 + dom元素
  // gsap.to(".gbox", { x: 500 });
  // gsap.from：和.to相反，从一个状态开始到当前状态。
  // setTimeout(() => gsap.to(box, { x: 200 }), 1000);
  // gsap.fromTo：可以自定义开始和结束状态。
  // sap.fromTo(
  //     box,
  //     {
  //       y: 0
  //     },
  //     {
  //       y: 50
  //     }
  // );g
  // gsap.set：立即设置属性，没有动画效果。
  // setTimeout(() => gsap.set(box, { x: 20 }), 2000);
  /*
   *  duration持续时间
   * repeat重复次数     ps:想让动画一直重复下去，使用repeat: -1
   *delay 动画延迟时间
   * repeatDelay  如果后面是repeat重复的动画，则不会有延迟了；如果我们想要为后面的任何重复运动添加延迟，可以使用repeatDelay属性
   *yoyo 如果为true，每次其他动画就会往相反方向运动（像yoyo球）默认fals
   *stagger 每个目标动画开始之间的时间（秒）
   *ease 控制动画期间的变化率，默认"power1.out"
   *
   * */
  // gsap.to(box, { x: 500, duration: 2, repeat: 2 });
  //   ps :尽可能的使用transforms，而不是布局属性，例如top、left或者margin，有更平滑的动画体验。
  // gsap.to(box, { rotation: 360, x: 10, yPercent: 50 }); //transform: rotate(360deg) translateX(10px) translateY(50%); （y Percent表示百分比元素的高度）
  /*
  GSAP支持CSS属性转为小驼峰形式，例如background-color变成backgroundColor
  * x: 200, // 默认px
  x: "+=200" // 相对值
  x: '40vw', // 视窗单位
  x: () => window.innerWidth / 2, // 函数计算
  rotation: 360 // 默认角度
  rotation: "1.25rad" // 使用弧度单位
  * 对于svg元素，我们添加attr属性额外的处理一些svg的属性，像width、height、fill、stroke、opacity等
  * */
  // gsap.to(box, {
  //   rotation: 360,
  //   duration: 1,
  //   delay: 1,
  //   repeat: 1
  // });
  // gsap.to(".purple", {
  //   //另外一个box
  //   rotation: 360,
  //   duration: 1,
  //   repeat: 1,
  //   repeatDelay: 1
  // });
  // stagger属性也是比较有趣的属性，我们可以利用它控制多个目标之间动画的延迟差，形成奇妙又好看的交错效果。
  // gsap.to(box, {
  //   //这里的box为数组就会交错
  //   duration: 0.5,
  //   opacity: 0,
  //   y: -100,
  //   stagger: 0.1,
  //   ease: "back.in"
  // });
  /**
   * 绝对值：在某个绝对秒数来执行动画。
   * <符和>符：”<”在上个动画开始，”>”在上个动画结束。
   * 相对符：+=在最后一个动画结束后，-=在最后一个动画结束前。
   * label值：直接用某个时间点的label名。
   */
  // 时间线
  /*  const t1 = gsap.timeline({
    defaults: {
      //下面继承
      scale: 1.2
    }
  }); //可以链式调用 t1.to.to
  t1.to(".red", { x: 400, duration: 1 });
  // 在1秒开始插入动画（绝对值）
  t1.to(
    ".green",
    {
      x: 300,
      duration: 2
    },
    1
  );
  // 在上个动画的开始插入动画
  t1.to(
    ".purple",
    {
      x: 300,
      duration: 1
    },
    "<"
  );
  // 在最后一个动画结束后一秒插入动画
  t1.to(
    ".orange",
    {
      x: 300,
      duration: 1
    },
    "+=1"
  );*/
  // label值则很好理解了，在某个时间点插入一个label，在这个label前面或者后面的时间来执行，我们看下它的用法：
  // const t1 = gsap.timeline();
  // t1.to(".green", { x: 400, duration: 1 })
  //   .add("myLabel", 2)
  //   .to(".purple", { x: 400, duration: 1 }, "myLabel+=1")
  //   .to(".orange", { x: 400, duration: 1 }, "myLabel-=1");
  /**
   * onComplete：动画完成时。
   * onStart：动画开始时
   * onUpdate：动画更新时。
   * onRepeat：动画重复时。
   * onReverseComplete：当动画在反转到达开始时。
   */
  // ScrollTrigger 使用
  // gsap.registerPlugin(ScrollTrigger);
  // gsap.to(".green", {
  //   rotation: 360,
  //   scale: 1.1,
  //   backgroundColor: "pink",
  //   scrollTrigger: {
  //     //通过滚动条来控制 而不是时间
  //     trigger: ".green", //目标元素
  //     scrub: true
  //   }
  // });
  // gsap.to(".purple", {
  //   rotation: 360,
  //   scale: 1.2,
  //   backgroundColor: "red",
  //   scrollTrigger: {
  //     trigger: ".purple",
  //     scrub: 1 //表示是否将动画效果链接到滚动条，随着滚动条平滑处理 如果是false（默认），随着元素出现在视窗内，直接触发动画，如果是true，则平滑动画 数字的话数值越大速度越慢
  //   }
  // });
});
// 案例 视觉滚动差
nextTick(() => {
  // 获取所有的 parallax-item 元素
  const parallaxItems = document.querySelectorAll(".parallax-item");

  // 对每个 parallax-item 元素进行操作
  parallaxItems.forEach(function (item) {
    gsap.fromTo(
      item,
      {
        backgroundPositionY: `-${window.innerHeight / 2}px`
      },
      {
        backgroundPositionY: `${window.innerHeight / 2}px`,
        ease: "none", // 设置动画过渡效果为无过渡效果
        scrollTrigger: {
          trigger: item, // 触发动画的元素
          scrub: true, // 开启 scrub 功能，使滚动更平滑
          scroller: ".parallax-container" // 指定要监听的滚动条元素
          // onUpdate: self => {
          //   let progress = self.progress.toFixed(2); // 获取滚动进
          // }
        }
      }
    );
  });
});
</script>

<style scoped lang="scss">
.parallax-container {
  //滚动范围
  overflow: scroll;
  scroll-behavior: smooth;

  .parallax-item {
    background-size: 100% 100%; /* 根据需要设置背景图片的大小 */
    background-repeat: no-repeat; /* 根据需要设置背景图片的重复模式 */
    position: relative; /* 重要：使背景图像相对于元素定位 */
    //第一个背景不处理
    &:first-child {
      //background-position-y: 0;
    }
    .text {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      text-align: center;
      color: white;
      font-size: 24px;
      p {
        margin: 0;
      }
    }
  }
}
</style>
